package cn.com.cetccst.hostsdk.internal;

import static cn.com.cetccst.hostsdk.HostSdkManager.logger;
import static cn.com.cetccst.sdk.channel.SSAct.SS_APP_KEY;
import static cn.com.cetccst.sdk.channel.SSAct.SS_APP_PACKAGE;
import static cn.com.cetccst.sdk.channel.SSAct.SS_SDK_VERSION;
import static cn.com.cetccst.sdk.modelbase.BaseReq.SSAPI_BASEREQ_TRANSACTION;
import static cn.com.cetccst.sdk.modelbase.BaseResp.ErrCode.ERR_APP_NOT_ADD;
import static cn.com.cetccst.sdk.modelbase.ConstantsAPI.COMMAND_SEND_AUTH;
import static cn.com.cetccst.sdk.modelbase.ConstantsAPI.COMMAND_UNKNOWN;
import static cn.com.cetccst.sdk.modelbase.ConstantsAPI.SSAPI_COMMAND_TYPE;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.NonNull;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import cn.com.cetccst.sdk.channel.SSAct;
import cn.com.cetccst.sdk.modelbase.BaseReq;
import cn.com.cetccst.sdk.modelbase.BaseResp;
import cn.com.cetccst.sdk.modelbase.ErrorMessage;
import cn.com.cetccst.sdk.modelbiz.SendAuth;
import cn.com.cetccst.sdk.openapi.SSApiImpl;

public class SSApiImplLocal extends SSApiImpl {

    private static SSApiImplLocal instance;
    private static final String TARGET_INVALID_ACTIVITY = "target_invalid_activity";
    private static String TARGET_FULL_ACTIVITY_NAME;
    private volatile Map<String, Target> responseTargetMap = new HashMap<>();
    private ISSAPIEventLocalHandler handler;

    private SSApiImplLocal(Context context) {
        super(context, SSAct.SSAPP_APP_KEY);
    }

    public static void initialize(@NonNull Context context) {
        if (instance == null)
            instance = new SSApiImplLocal(context);
    }

    public static SSApiImplLocal getInstance(Context context) {
        if(instance == null && context!=null){
            initialize(context);
        }
        return instance;
    }

    public void handleIntent(Intent intent) {

        try {
            int type = intent.getIntExtra(SSAPI_COMMAND_TYPE, COMMAND_UNKNOWN);
            String appKey = intent.getStringExtra(SS_APP_KEY);
            String appPackage = intent.getStringExtra(SS_APP_PACKAGE);
            int requestVersion = intent.getIntExtra(SS_SDK_VERSION, 0);

            logger.debug("handleIntent [" + type + "][" + appKey + "][" + appPackage + "][" + requestVersion + "]");

            if (handler == null) {
                responseError(intent, type, appKey, appPackage, SDKErrorCode.ERR_NOT_SUPPORT);
                return;
            }
            switch (type) {
                case COMMAND_SEND_AUTH:
                    handler.onReq(appKey, appPackage, new SendAuth.Req(intent.getExtras()));
                    return;
                default:
                    responseError(intent, type, appKey, appPackage, SDKErrorCode.ERR_NOT_SUPPORT);
                    return;
            }
        } catch (Exception excepition) {
            logger.error("handleIntent failed", excepition);
        }
    }

    private void responseError(Intent intent, int type, String appKey, String appPackage, int errorCode) {
        String transaction = intent.getStringExtra(SSAPI_BASEREQ_TRANSACTION);
        holdResponseTarget(appPackage, transaction);
        BaseResp baseResp = BaseResp.createRespByType(type);
        SDKErrorCode.setDefaultErrorInfo(baseResp, errorCode);
        baseResp.transaction = transaction;
        sendResp(appKey, baseResp);
    }

    @Override
    public int sendReqInner(BaseReq req) {
        if (!req.checkArgs()) {
            logger.error("sendReqInner error: " + ErrorMessage.getErrorMessage(SDKErrorCode.ERR_PARAMETER_NULL));
            return SDKErrorCode.ERR_PARAMETER_NULL;
        } else {
            logger.info("sendReq, " + req);
            req.appKey = appKey;
            Bundle bundle = new Bundle();
            req.toBundle(bundle);
            SSAct.Args args = new SSAct.Args();
            args.mBundle = bundle;
            args.mTargetPkgName = TARGET_PACKAGE_NAME;
            args.mTargetClassName = TARGET_FULL_ACTIVITY_NAME;

            return SSAct.send(context, args, false);
        }
    }

    public synchronized boolean sendReq(String packageName, BaseReq req, IResponseListener responseListener) {
        refreshTarget(packageName);
        if (TARGET_INVALID_ACTIVITY.equals(TARGET_FULL_ACTIVITY_NAME)) {
            responseSendFailed(req, ERR_APP_NOT_ADD, responseListener);
            return true;
        }
        return sendReq(req, responseListener);
    }


    public int getSSAppSupportAPI() {
        return SSAct.getSdkVersion(context, context.getPackageName());
    }

    public synchronized boolean sendResp(String appKey, BaseResp resp) {
        logger.debug("sendResp = " + resp);
        Target target = responseTargetMap.remove(resp.transaction);

        if (target == null) {
            logger.debug("sendResp target = " + target);
            return false;
        }

        logger.debug("sendResp targetActivity = " + target.targetActivity);

        Bundle bundle = new Bundle();
        resp.toBundle(bundle);

        SSAct.Args args = new SSAct.Args();
        args.mBundle = bundle;
//
        return SSAct.sendBR(context, appKey, args, null);
    }

    /**
     * 发送位置的刷新，以appkey为准，apppackage为辅
     *
     * @param appPackage 应用的包名
     */
    private void refreshTarget(String appPackage) {
        if (!appPackage.equals(context.getPackageName())) {
            TARGET_PACKAGE_NAME = appPackage;
            TARGET_FULL_ACTIVITY_NAME = appPackage;
            return;
        } else {
            //TODO 内部集成，可以参看橙讯接入SDK, 目前不考虑有外部应用结成到内部
        }

        TARGET_PACKAGE_NAME = context.getPackageName();
        TARGET_FULL_ACTIVITY_NAME = TARGET_INVALID_ACTIVITY;

        logger.debug("refreshTarget targetActivity = " + TARGET_FULL_ACTIVITY_NAME);
    }

    public void holdResponseTarget(final String appPackage, String transaction) {
        tryToClearResponseTarget();
        Target target = new Target();
        target.targetPackage = appPackage;
        if (context.getPackageName().equals(appPackage)) {
            //TODO 如果是内部集成的应用，需要查询注册的packageName（可参考橙讯接入SDK）
            //目前不考虑此情况
        } else {
            target.targetActivity = appPackage;
        }
        responseTargetMap.put(transaction, target);
    }

    private void tryToClearResponseTarget() {
        Iterator<Map.Entry<String, Target>> entryIterator = responseTargetMap.entrySet().iterator();
        while (entryIterator.hasNext()) {
            Map.Entry<String, Target> entry = entryIterator.next();
            if (isTransactionExpired(entry.getKey())) {
                entryIterator.remove();
            }
        }
    }

    public void setSSAPIEventLocalHandler(ISSAPIEventLocalHandler handler) {
        this.handler = handler;
    }

    private class Target {
        public String targetPackage;
        public String targetActivity;
    }
}
